﻿using Microsoft.Xna.Framework;
using SoulDoorEngine.Framework;
using SoulDoorEngine.Framework.Components;
using SoulDoorEngine.Framework.Services;
using SoulDoorEngine.Framework.Utilities;

namespace SoulDoorEngine.Components.Cameras
{
    //基础相机类
    public class Camera : SoulDoorEngine.Framework.Components.Component, I3DComponent
    {
        Vector3 position = Vector3.Zero;
        Matrix rotationMatrix = Matrix.Identity;
        Vector3 target = new Vector3(0, 0, -1);
        Vector3 up = Vector3.Up;
        Matrix view;
        Matrix projection;

        //观测目标
        public virtual Vector3 Target
        { get { return target; } set { target = value; } }

        public virtual Matrix View
        { get { return view; } set { view = value; } }
        public virtual Matrix Projection
        { get { return projection; } set { projection = value; } }

        public virtual Vector3 Up
        { get { return up; } set { up = value; } }

        //I3DComponent接口成员
        public virtual Vector3 Position { get { return position; } set { position = value; } }
        public virtual Vector3 Scale { get { return Vector3.One; } set { } }
        public Vector3 EulerRotation
        {
            get { return MathUtil.MatrixToVector3(Rotation); }
            set { Rotation = MathUtil.Vector3ToMatrix(value); }
        }
        //旋转矩阵
        public virtual Matrix Rotation
        { get { return rotationMatrix; } set { rotationMatrix = value; } }

        public virtual BoundingBox BoundingBox
        { get { return new BoundingBox(Position - Vector3.One, Position + Vector3.One); } }

        //构造函数
        public Camera(SoulDoorEngine.Framework.Screens.Screen Parent) : base(Parent) { }
        public Camera() : base() { }

        //更新相机
        public override void Update()
        {
            //计算相机位置与目标间的方向
            Vector3 newForward = Target - Position;
            newForward.Normalize();

            Matrix rotationMatrixCopy = this.Rotation;
            rotationMatrixCopy.Forward = newForward;

            Vector3 referenceVector = Vector3.Up;

            // On the slim chance that the camera is pointed perfectly parallel with
            // the Y Axis, we cannot use cross product with a parallel axis, so we
            // change the reference vector to the forward axis (Z).
            if (rotationMatrixCopy.Forward.Y == referenceVector.Y
                || rotationMatrixCopy.Forward.Y == -referenceVector.Y)
                referenceVector = Vector3.Backward;

            //计算旋转矩阵的另一部分
            rotationMatrixCopy.Right = Vector3.Cross(this.Rotation.Forward,
                referenceVector);
            rotationMatrixCopy.Up = Vector3.Cross(this.Rotation.Right,
                this.Rotation.Forward);

            this.Rotation = rotationMatrixCopy;

            //更新Up向量
            Up = Rotation.Up;

            //更新View及Projection
            View = Matrix.CreateLookAt(Position, Target, Up);
            Projection = MathUtil.CreateProjectionMatrix();
        }
    }
}
